package com.flx.noodle.websocket.adapter;

import com.flx.noodle.websocket.entity.SSOUser;
import com.flx.noodle.websocket.service.ChatService;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import util.WsConstant;

import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by fenglixiong on 2017/10/2.
 */
@Component
public class ChatSessionAdapter{

    protected final Log logger = LogFactory.getLog(getClass());

    @Autowired
    private ChatService chatService;

    /**
     * userid -> ws_sessionid，里面是所有房间的所有人，要看这个人连接的哪个房间 ，就看这个key对用的value
     */
    private Map<Integer, WebSocketSession> userWsMap;

    /**
     * chat_sessionId -> wsList 维护所有的房间，即已经创建好的房间里面的所有用户list
     */
    private Map<Integer, List<WebSocketSession>> chatRoomWsMap;

    private Gson gson = new GsonBuilder().create();

    /**
     * @param user
     * @param chatSessionId -- rs_roadshow_lastmsg.id 代表了聊天室的号码，每个需要聊天的业务对象需要在创建对象时，同时创建一个lastmsg记录从而获取唯一的聊天室编号
     * @param session
     */
    public synchronized void addUserSession(SSOUser user, Integer chatSessionId, WebSocketSession session) {
        session.getAttributes().put("chatSessionId", chatSessionId);
        boolean _need_add_user_ = true;
        if(userWsMap.containsKey(user.getUserId())){
            logger.info("user already connected with WSID:" + userWsMap.get(user.getUserId()).getId());
            if(userWsMap.get(user.getUserId()).getId().equalsIgnoreCase(session.getId())){
                logger.info("user WSID no change." + session.getId());
            }else {
                userWsMap.remove(user.getUserId());
                logger.info("user WSID changed, new WSID:" + session.getId());
            }
        }
        if(_need_add_user_) {
            userWsMap.put(user.getUserId(), session);
            logger.info("user added WSID:" + session.getId());
        }

        //判断chatWsMap是否有当前房间
        if (chatRoomWsMap.containsKey(chatSessionId)) {
            logger.info("chatRoomWsMap contains chatSessionId [" + chatSessionId + "]");
        } else {
            //添加房间chatSessionId
            chatRoomWsMap.put(chatSessionId, Collections.synchronizedList(new ArrayList()));
            logger.info("chatRoomWsMap create new chatSessionId [" + chatSessionId + "]");
        }

        //判断当前连接用户是否在当前房间中， 没有则添加
        if (findSession(this.chatRoomWsMap.get(chatSessionId), session.getId()) == null) {
            session.getAttributes().put(WsConstant.WEBSOCKET_SESSION_KEY,user);//session中存放这条session的拥有者
            this.chatRoomWsMap.get(chatSessionId).add(session);

            logger.info("chatRoomWsMap[" + chatRoomWsMap.hashCode() + "]=" + chatRoomWsMap);
            logger.info("chatSessionId [" + chatSessionId + "] " + chatRoomWsMap.get(chatSessionId) + " contains " +
                    chatRoomWsMap.get(chatSessionId).size() + " wsSessionIds");

            //成功连接，添加系统消息
            logger.info(user.getUserId() + " 进入房间推送start");
            chatService.connectWsPush(chatSessionId, user);
            logger.info(user.getUserId() + " 进入房间推送finished");
            //成功连接，房间人数更新推送
            logger.info(user.getUserId() + " 连接ws成功，房间人数更新推送start");
            chatService.onlinePush(chatSessionId);
            logger.info(user.getUserId() + " 连接ws成功，房间人数更新推送finished");
        }

    }

    public synchronized WebSocketSession findSession(List<WebSocketSession> sessions, String id) {
        for (int i = sessions.size() - 1; i >= 0; i--) {
            WebSocketSession sess = sessions.get(i);
            logger.info("check session:" + sess.getId() + "\t" + sess.isOpen());
            if (!sess.isOpen()) {
                logger.info("session has been closed, remove:" + sess.getId());
                sessions.remove(i);
            } else if (sess.getId().equals(id)) {
                return sess;
            }
        }
        return null;
    }

    public synchronized void removeSession(int userid, Integer chatSessionId, String sessionid) {
        userWsMap.remove(userid);
        logger.info("userWsMap remove user[" + userid + "]");

        List<WebSocketSession> sessions = chatRoomWsMap.get(chatSessionId);
        if (sessions != null && sessions.size() > 0) {
            for (int i = sessions.size() - 1; i >= 0; i--) {
                WebSocketSession sess = sessions.get(i);
                logger.info("check session:" + sess.getId() + "\tisopen:" + sess.isOpen());
                if (sess.getId().equals(sessionid) || !sess.isOpen()) {
                    logger.info("chatRoomWsMap chatSessionId[" + chatSessionId + "] remove closed wsSessionId[" + sess.getId() + "]");
                    sessions.remove(i);
                }
            }
        }

        logger.info(userid + " remove Session，房间人数更新推送start");
        chatService.onlinePush(chatSessionId);
        logger.info(userid + " remove Session，房间人数更新推送finished");
    }

    //CHATREFLASH
    public List<SSOUser> sendNotifyToWebSocketClient(int chatSessionId, Map<String, Object> dataMap, String command) throws Exception {
//        logger.info("chatRoomWsMap------------->" + chatRoomWsMap);
        List<WebSocketSession> sessions = this.chatRoomWsMap.get(chatSessionId);
        logger.info("chatSessionId[" + chatSessionId + "] contains WsSessionId size : " + (sessions == null ? 0 : sessions.size()));
        List<SSOUser> sent_to_users = new ArrayList();  //发送了给哪些用户
        try {
            if (sessions != null && sessions.size() > 0) {
                for (WebSocketSession session : sessions) {
                    logger.info("socket response send to sessionId:" + session.getId());
                    if (session.isOpen()) {
                        Map<String, Object> pushMap = new HashMap<String, Object>();
                        pushMap.put("command", command);

                        pushMap.put("data", gson.toJson(dataMap));
                        session.sendMessage(new TextMessage(gson.toJson(pushMap)));
                        logger.info("socket send to sessionId:" + session.getId() + "  successed");

                        /**
                         * 在websocket的attribute中存放了用户对象
                         */
                        SSOUser user = (SSOUser) session.getAttributes().get(WsConstant.WEBSOCKET_SESSION_KEY);
                        if (user != null) {
                            sent_to_users.add(user);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.info("【聊天异常】[CHATREFLASH]sendNotifyToWebSocketClient出现异常!该异常可能是网页端关闭直播引起的：" + e);
        }
        return sent_to_users;
    }

    public int getRoomPersonNumber(String chatSessionId) {
        if (chatRoomWsMap == null || !chatRoomWsMap.containsKey(chatSessionId)) return 1;
        return chatRoomWsMap.get(chatSessionId) != null ? chatRoomWsMap.get(chatSessionId).size() : 1;
    }

    public List<SSOUser> getUserListInChatRoom(Integer chatSessionId) {
        List<SSOUser> userList = new ArrayList<SSOUser>();
        List<WebSocketSession> webSocketSessionList = chatRoomWsMap.get(chatSessionId);
        if (webSocketSessionList != null && webSocketSessionList.size() > 0) {
            for (WebSocketSession session : webSocketSessionList) {
                Object uObj = session.getAttributes().get(WsConstant.WEBSOCKET_SESSION_KEY);
                if (uObj != null) {
                    userList.add((SSOUser) uObj);
                }
            }
        }
        return userList;
    }

}
